package dfsketches.gr3d;

public class TestingScene extends Scene {

	public TestingScene() {
		super();
		
		Model house = testingHouse();
		Model door = testingHouseDoor();
		Model terrain = terrain();
		Model sky = sky();
		Model tree = testingTree();
		models.put("house", house);
		models.put("door", door);
		models.put("terrain", terrain);
		models.put("sky", sky);
		models.put("tree", tree);
		
	}
	
	public static Model terrain() {
		ModelConstructor terrConstr  = new ModelConstructor();
		
		BoneConstructor terrBoneConstr = new BoneConstructor();
		Vertex[] corners = terrBoneConstr.addRectangle(
				new Vertex(-1000f, 0f, -1000f),
				new Vertex(2000f, 0f, 0f),
				new Vertex(0f, 0f, 2000f));
		Bone terrBone = terrBoneConstr.construct();
		
		terrConstr.addRectangle(0xFF00A000, corners);
		terrConstr.setMainBone(terrBone);
		
		return terrConstr.construct();
	}
	
	public static Model sky() {
		BoneConstructor skyBoneConstr = new BoneConstructor();
		Vertex[] corners = skyBoneConstr.addBox(
				new Vertex(-1000f, -1000f, -1000f),
				new Vector3D(2000f, 0f, 0f),
				new Vector3D(0f, 2000f, 0f),
				new Vector3D(0f, 0f, 2000f));
		Bone terrBone = skyBoneConstr.construct();
		
		ModelConstructor skyConstr = new ModelConstructor();
		skyConstr.addBox(0xFFA0A0FF, corners);
		skyConstr.setMainBone(terrBone);
		return skyConstr.construct();
	}
	
	public static Model testingHouse() {
		ModelConstructor houseConstr = new ModelConstructor();
		
		Vertex roofFront = new Vertex( 0f, 2.8f, -1f);
		Vertex roofBack  = new Vertex( 0f, 2.8f,  1f);
		Vertex cornerTFL = new Vertex(-1f,   2f, -1f);
		Vertex cornerTFR = new Vertex( 1f,   2f, -1f);
		Vertex cornerTBL = new Vertex(-1f,   2f,  1f);
		Vertex cornerTBR = new Vertex( 1f,   2f,  1f);
		Vertex cornerBFL = new Vertex(-1f,   0f, -1f);
		Vertex cornerBFR = new Vertex( 1f,   0f, -1f);
		Vertex cornerBBL = new Vertex(-1f,   0f,  1f);
		Vertex cornerBBR = new Vertex( 1f,   0f,  1f);

		BoneConstructor mainDetailsConstr = new BoneConstructor();
		mainDetailsConstr.addVertex(roofFront);
		mainDetailsConstr.addVertex(roofBack);
		mainDetailsConstr.addVertex(cornerTFR);
		mainDetailsConstr.addVertex(cornerTFL);
		mainDetailsConstr.addVertex(cornerTBR);
		mainDetailsConstr.addVertex(cornerTBL);
		mainDetailsConstr.addVertex(cornerBFR);
		mainDetailsConstr.addVertex(cornerBFL);
		mainDetailsConstr.addVertex(cornerBBR);
		mainDetailsConstr.addVertex(cornerBBL);

		//Roof
		houseConstr.addTriangle(0xFF801000, roofFront, cornerTFL, cornerTFR);
		houseConstr.addTriangle(0xFF801000,  roofBack, cornerTBL, cornerTBR);
		houseConstr.addRectangle(0xFF802000, roofFront, roofBack, cornerTFL, cornerTBL);
		houseConstr.addRectangle(0xFF802000, roofFront, roofBack, cornerTFR, cornerTBR);
		
		//Walls
 		houseConstr.addRectangle(0xFFD0C0A0, cornerTFR, cornerTFL, cornerBFR, cornerBFL);
		houseConstr.addRectangle(0xFFD0C0A0, cornerTBR, cornerTBL, cornerBBR, cornerBBL);
		houseConstr.addRectangle(0xFFD0B8A0, cornerTFR, cornerTBR, cornerBFR, cornerBBR);
		houseConstr.addRectangle(0xFFD0B8A0, cornerTFL, cornerTBL, cornerBFL, cornerBBL);
		
		//Stack
		Vertex stackTFL = new Vertex(-0.8f, 2.9f, -0.8f);
		Vertex stackTFR = new Vertex(-0.7f, 2.9f, -0.8f);
		Vertex stackTBL = new Vertex(-0.8f, 2.9f, -0.7f);
		Vertex stackTBR = new Vertex(-0.7f, 2.9f, -0.7f);
		Vertex stackBFL = new Vertex(-0.8f, 2.0f, -0.8f);
		Vertex stackBFR = new Vertex(-0.7f, 2.0f, -0.8f);
		Vertex stackBBL = new Vertex(-0.8f, 2.0f, -0.7f);
		Vertex stackBBR = new Vertex(-0.7f, 2.0f, -0.7f);
		mainDetailsConstr.addVertex(stackTFL);
		mainDetailsConstr.addVertex(stackTFR);
		mainDetailsConstr.addVertex(stackTBL);
		mainDetailsConstr.addVertex(stackTBR);
		mainDetailsConstr.addVertex(stackBFL);
		mainDetailsConstr.addVertex(stackBFR);
		mainDetailsConstr.addVertex(stackBBL);
		mainDetailsConstr.addVertex(stackBBR);
		houseConstr.addRectangle(0xFFA08080, stackTFR, stackTFL, stackBFR, stackBFL);
		houseConstr.addRectangle(0xFFA08080, stackTBR, stackTBL, stackBBR, stackBBL);
		houseConstr.addRectangle(0xFFA08080, stackTFR, stackTBR, stackBFR, stackBBR);
		houseConstr.addRectangle(0xFFA08080, stackTFL, stackTBL, stackBFL, stackBBL);

		//Smoke
		BoneConstructor smokeConstr = new BoneConstructor();
		Vertex smokeBegin = new Vertex(-0.75f,2.75f, -0.75f);
		Vertex smokeEnd1  = new Vertex(  -1f,   4f,-0.3f);
		Vertex smokeEnd2  = new Vertex(-1.1f,   4f,-0.4f);
		Vertex smokeEnd3  = new Vertex(-1.2f,   4f,-0.3f);
		smokeConstr.addVertex(smokeBegin);
		smokeConstr.addVertex(smokeEnd1);
		smokeConstr.addVertex(smokeEnd2);
		smokeConstr.addVertex(smokeEnd3);
		houseConstr.addTriangle(0xFF101010, smokeBegin, smokeEnd1, smokeEnd2);
		houseConstr.addTriangle(0xFF101010, smokeBegin, smokeEnd3, smokeEnd2);
		houseConstr.addTriangle(0xFF101010, smokeBegin, smokeEnd1, smokeEnd3);
		houseConstr.addTriangle(0xFF101010, smokeEnd1, smokeEnd3, smokeEnd2);
		Bone smoke = smokeConstr.construct();
		mainDetailsConstr.addSubBone(smoke);
		
		Bone mainDetails = mainDetailsConstr.construct();
		houseConstr.setMainBone(mainDetails);

		SplineConstructor smokeSplineConstr = new SplineConstructor(SplineType.Linear, true);
		smokeSplineConstr.addPosition(0f, Matrix3D.getUniteMatrix());
		Matrix3D smokeM2;
		smokeM2 = Matrix3D.getTranslationMatrix(-smokeBegin.x, -smokeBegin.y, -smokeBegin.z);
		smokeM2.multiplyRight(Matrix3D.getScaleMatrix(1.5f, 1.5f, 1.5f));
		smokeM2.multiplyRight(Matrix3D.getTranslationMatrix(smokeBegin.x, smokeBegin.y, smokeBegin.z));
		smokeSplineConstr.addPosition(0.9f, smokeM2);
		smokeSplineConstr.addPosition(1f, Matrix3D.getUniteMatrix());
		
		CommonAnimationConstructor smokeAnimationConstr = new CommonAnimationConstructor();
		smokeAnimationConstr.addSplineForBone(smoke, smokeSplineConstr.construct());

		houseConstr.addAnimation("stand", smokeAnimationConstr.construct());
		return houseConstr.construct();
	}
	
	public static Model testingHouseDoor() {
		BoneConstructor doorConstr = new BoneConstructor();
		Vertex doorLT = new Vertex(-0.2f, 1.5f, -1.03f);
		Vertex doorRT = new Vertex( 0.6f, 1.5f, -1.03f);
		Vertex doorLB = new Vertex(-0.2f, 0.1f, -1.03f);
		Vertex doorRB = new Vertex( 0.6f, 0.1f, -1.03f);
		doorConstr.addVertex(doorLT);
		doorConstr.addVertex(doorRT);
		doorConstr.addVertex(doorLB);
		doorConstr.addVertex(doorRB);

		SplineConstructor doorSplineConstr = new SplineConstructor(SplineType.Linear);
		Matrix3D angle = Matrix3D.getUniteMatrix();
		Matrix3D rot = Matrix3D.getPolarRotationYMatrix(-0.01f, 0.6f, -1.03f);
		float time = 0;
		for (int i = 1; i <= 100; i++) {
			doorSplineConstr.addPosition(time += 0.01f, angle);
			angle = new Matrix3D(angle);
			angle.multiplyRight(rot);
		}
		
		Bone doorBone = doorConstr.construct();
		CommonAnimationConstructor doorAnimationConstr = new CommonAnimationConstructor();
		doorAnimationConstr.addSplineForBone(doorBone, doorSplineConstr.construct());
		
		ModelConstructor doorModelConstr = new ModelConstructor();
		doorModelConstr.addRectangle(0xFFA0F0F0, doorLT, doorRT, doorLB, doorRB);
		doorModelConstr.addAnimation("open", doorAnimationConstr.construct());
		doorModelConstr.setMainBone(doorBone);
		return doorModelConstr.construct();
	}
	
	public static Model testingTree() {
		BoneConstructor trunkConstr = new BoneConstructor();
		Vertex[] trunk = trunkConstr.addBox(
				new Vertex(-0.1f, 0f, -0.1f),
				new Vector3D(0.2f, 0f, 0f),
				new Vector3D(0f, 0f, 0.2f),
				new Vector3D(0f, 1f, 0f));

		BoneConstructor leaves1Constr = new BoneConstructor();
		BoneConstructor leaves2Constr = new BoneConstructor();
		BoneConstructor leaves3Constr = new BoneConstructor();
		Vertex[] leaves1 = leaves1Constr.addBox(
				new Vertex(-0.5f, 0.9f, -0.5f),
				new Vector3D(1.0f, 0f, 0f),
				new Vector3D(0f, 0f, 1.0f),
				new Vector3D(0f, 2.0f, 0f));
		Vertex[] leaves2 = leaves2Constr.addBox(
				new Vertex(-0.7f, 1.2f, -0.7f),
				new Vector3D(0.8f, 0f, 0f),
				new Vector3D(0f, 0f, 0.8f),
				new Vector3D(0f, 0.8f, 0f));
		Vertex[] leaves3 = leaves3Constr.addBox(
				new Vertex(-0.1f, 1.8f, -0.6f),
				new Vector3D(0.7f, 0f, 0f),
				new Vector3D(0f, 0f, 1.2f),
				new Vector3D(0f, 0.8f, 0f));
		Bone leaves1Bone = leaves1Constr.construct();
		Bone leaves2Bone = leaves2Constr.construct();
		Bone leaves3Bone = leaves3Constr.construct();
		trunkConstr.addSubBone(leaves1Bone);
		trunkConstr.addSubBone(leaves2Bone);
		trunkConstr.addSubBone(leaves3Bone);
		
		Matrix3D med = Matrix3D.getUniteMatrix();
		Matrix3D dev = Matrix3D.getZeroMatrix();
		dev.m14 = dev.m24 = dev.m34 = 0.000f;
		FluctuatingAnimationConstructor leavesAnimConstr = new FluctuatingAnimationConstructor();
		leavesAnimConstr.addPairForBone(leaves1Bone, med, dev);
		leavesAnimConstr.addPairForBone(leaves2Bone, med, dev);
		leavesAnimConstr.addPairForBone(leaves3Bone, med, dev);
		
		Bone trunkBone = trunkConstr.construct();

		ModelConstructor treeConstr = new ModelConstructor();
		treeConstr.addBox(0xFF701010, trunk);
		treeConstr.addBox(0xFF20B020, leaves1);
		treeConstr.addBox(0xFF20C020, leaves2);
		treeConstr.addBox(0xFF00B000, leaves3);
		treeConstr.setMainBone(trunkBone);
		
		treeConstr.addAnimation("stand", leavesAnimConstr.construct());
		return treeConstr.construct();
	}
	
	public static Model house() {
//		BoneConstructor cWindow = new BoneConstructor();
//		BoneConstructor cWalls = new BoneConstructor();
//		BoneConstructor cDoor = new BoneConstructor();
//		
		return null;
	}

}